#include <stdlib.h>
#include <stdio.h>

#define uc unsigned char
typedef struct {
	uc r, g, b;
} pixel;

// function to apply the smooth 
void smooth(pixel ** in, pixel ** out, int nrow, int ncol, int SMOOTH_SQUARE) 
{
	int i, j, k, l;
	// for which pixel (i,j) calculates the smooth
	for(i = 0; i < nrow; i++) {
		for(j = 0; j < ncol; j++) {

			// sums for each component of RGB 
			int sumr, sumg, sumb;
			sumr = sumg = sumb = 0;

			// considers 5x5 square 
			for(k = i - SMOOTH_SQUARE/2	; k <= i + SMOOTH_SQUARE/2; k++) {

				for(l = j - SMOOTH_SQUARE/2; l <= j + SMOOTH_SQUARE/2; l++) {

					// assumes zero for border pixels
					if( k < 0 || k >= nrow || l < 0 || l >= ncol)
						continue;

					// acumulate
					sumr += in[k][l].r;
					sumg += in[k][l].g;
					sumb += in[k][l].b;
				}
			}

			// calculate the mean
			out[i][j].r = sumr/(SMOOTH_SQUARE * SMOOTH_SQUARE);
			out[i][j].g = sumg/(SMOOTH_SQUARE * SMOOTH_SQUARE);
			out[i][j].b = sumb/(SMOOTH_SQUARE * SMOOTH_SQUARE);
		}
	}
}

int main (int argc, char ** argv) 
{ 
	struct timeval start_total, end_total;
	struct timeval start_seq, end_seq;
	gettimeofday(&start_total, NULL);

	// require arguments to run
	if( argc != 4) {
		printf("usage: ./seq <file_input_name.ppm> <file_output_name.ppm> <smooth_square_side(odd-number)>\n");
		exit(1);
	}

	// open file
	FILE * fp = fopen(argv[1], "r");
	FILE * fout = fopen(argv[2], "w");
	char encoding[4];
	int ncol, nrow;
	uc maxValue;
	int i, j;
	int SMOOTH_SQUARE = atoi(argv[3]);

	// read file header
	fscanf(fp, "%s", encoding);
	fscanf(fp, "%d %d", &ncol, &nrow);
	fscanf(fp, "%hhu", &maxValue);

	// alloc memory for both matrices
	pixel ** in = (pixel **) malloc ( nrow * sizeof (pixel *) );
	pixel ** out = (pixel **) malloc ( nrow * sizeof (pixel *) );
	for(i = 0; i < nrow; i++) {
		in[i] = (pixel *) malloc ( ncol * sizeof (pixel ) );
		out[i] = (pixel *) malloc ( ncol * sizeof (pixel ) );
	}

	// read image
	for(i = 0; i < nrow; i++) {
		for(j = 0; j < ncol; j++) 
			fscanf(fp, "%hhu %hhu %hhu", &in[i][j].r, &in[i][j].g, &in[i][j].b);
	}

	gettimeofday(&start_seq, NULL);

	// smooth
	smooth(in, out, nrow, ncol, SMOOTH_SQUARE);

	gettimeofday(&end_seq, NULL);

	// write the results in output file
	fprintf(fout, "%s\n", encoding);
	fprintf(fout, "%d %d\n", ncol, nrow);
	fprintf(fout, "%hhu\n", maxValue);
	for(i = 0; i < nrow; i++) {
		for(j = 0; j < ncol; j++) 
			fprintf(fout, "%hhu %hhu %hhu ", out[i][j].r, out[i][j].g, out[i][j].b);
		fprintf(fout, "\n");
	}

	// free memory
	for(i = 0; i < nrow; i++)
		free(in[i]), free(out[i]);
	free(in);
	free(out);
	fclose(fp);
	fclose(fout);

	gettimeofday(&end_total, NULL);

	double result_total = end_total.tv_sec - start_total.tv_sec + (end_total.tv_usec - start_total.tv_usec) / 1000000.0;
	double result_seq = end_seq.tv_sec - start_seq.tv_sec + (end_seq.tv_usec - start_seq.tv_usec) / 1000000.0;

	printf("%lf\n", result_seq);
	//printf("Sequential processing + I/O - TOTAL : %lfs\n", result_total);

	return 0;
}
